package cn.com.ry.framework.monitormeter.metric.jdbc;

import cn.com.ry.framework.monitormeter.instrument.linklog.LinkLogMeterRegistry;
import com.zaxxer.hikari.HikariDataSource;
import com.zaxxer.hikari.pool.HikariPool;
import io.micrometer.core.instrument.Gauge;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Tag;
import io.micrometer.core.instrument.Tags;
import io.micrometer.core.instrument.binder.MeterBinder;
import io.micrometer.prometheus.PrometheusMeterRegistry;
import org.springframework.beans.DirectFieldAccessor;

import javax.sql.DataSource;

public class HikariDataSourcePoolMetrics implements MeterBinder {

    private String name;
    private HikariDataSource hikariDataSource;
    private Iterable<Tag> tags;

    public HikariDataSourcePoolMetrics(String name, DataSource dataSource, Iterable<Tag> tags) {
        if (dataSource != null && dataSource instanceof HikariDataSource) {
            this.hikariDataSource = (HikariDataSource) dataSource;
        }
        this.name = name;
        this.tags = tags;
    }

    public HikariDataSourcePoolMetrics(String name, DataSource dataSource) {
        if (dataSource != null && dataSource instanceof HikariDataSource) {
            this.hikariDataSource = (HikariDataSource) dataSource;
        }
        this.name = name;
        this.tags = Tags.of("linklog.jdbc.type", "hikari");
    }


    private HikariPool getHikariPool() {
        return (HikariPool) new DirectFieldAccessor(hikariDataSource).getPropertyValue("pool");
    }

    @Override
    public void bindTo(MeterRegistry registry) {
        if (hikariDataSource != null && registry != null) {
            if (registry instanceof LinkLogMeterRegistry) {
                Gauge.builder("jdbc.connections.hikari." + name + ".active", getHikariPool(), HikariPool::getActiveConnections)
                        .tags(tags)
                        .description("hikari监控，当前占用连接数")
                        .register(registry);
                Gauge.builder("jdbc.connections.hikari." + name + ".max", hikariDataSource, HikariDataSource::getMaximumPoolSize)
                        .tags(tags)
                        .description("hikari监控，最多连接池数量")
                        .register(registry);
                Gauge.builder("jdbc.connections.hikari." + name + ".min", hikariDataSource, HikariDataSource::getMinimumIdle)
                        .tags(tags)
                        .description("hikari监控，初始连接数")
                        .register(registry);
            } else if (registry instanceof PrometheusMeterRegistry) {
                Gauge.builder("jdbc.connections.active", getHikariPool(), HikariPool::getActiveConnections)
                        .tags(Tags.of("datasource.name", name))
                        .description("hikari监控，当前占用连接数")
                        .register(registry);
                Gauge.builder("jdbc.connections.max", hikariDataSource, HikariDataSource::getMaximumPoolSize)
                        .tags(Tags.of("datasource.name", name))
                        .description("hikari监控，最多连接池数量")
                        .register(registry);
                Gauge.builder("jdbc.connections.min", hikariDataSource, HikariDataSource::getMinimumIdle)
                        .tags(Tags.of("datasource.name", name))
                        .description("hikari监控，初始连接数")
                        .register(registry);
            }

        }
    }

}
